import { Ref, computed, reactive, ref, toRefs } from 'vue'
import { BaseResponse, PaginationResult } from '@/types/api'

export type UsePaginationApi<D> = (params?: Record<string, unknown>) => Promise<BaseResponse<PaginationResult<D>>>

export type UsePaginationOptions<D> = {
	immediate?: boolean;
	pageSize?: number;
	showLoading?: boolean;
	onError?: (e?: unknown) => void;
	onSuccess?: (result?: PaginationResult<D>) => void;
}

export function usePagination<D = any, P extends any[] = []>(api: UsePaginationApi<D>, options?: UsePaginationOptions<D>) {
	const {
		immediate = true,
		pageSize = 10,
		showLoading = false,
		onError,
		onSuccess,
	} = options || {}

	const page = ref(1)
	// const list = ref<D[]>([])
	// 这里不能使用ref泛型给D泛型,会推导为UnwrapRefSimple类型
	const list: Ref<D[]> = ref([])
	const total = ref(0)

	const state = reactive({
		isLoading: false,
		isRefreshing: false,
		isFinished: false,
		isError: false,
	})

	let isFetching = false

	let _showLoading = false

	const getList = async (isRefresh = false) => {
		if (isFetching) return
		isFetching = true

		if (!isRefresh) {
			if (state.isFinished) return

			state.isLoading = true
		} else {
			page.value = 1
			state.isFinished = false
			state.isLoading = true
		}

		state.isError = false

		try {
			if (showLoading && !_showLoading) {
				_showLoading = true
				uni.showLoading({
					mask: true,
				})
			}

			const params = {
				page: page.value,
				limit: pageSize,
			}
			const response = await api(params)

			if (response.code === 1) {
				const result = response.data

				if (isRefresh) {
					list.value = result.data
				} else {
					list.value = [
						...list.value,
						...result.data,
					]
				}

				total.value = result.total
				state.isFinished = result.current_page >= result.last_page
				console.log(state.isFinished)
				if (!state.isFinished) {
					page.value += 1
				}

				onSuccess?.(result)
			}
		} catch (e) {
			state.isError = true
			onError?.(e)
		} finally {
			state.isRefreshing = false
			state.isLoading = false

			isFetching = false
			if (showLoading && _showLoading) {
				_showLoading = false
				uni.hideLoading()
			}
		}
	}

	const refresh = () => getList(true)

	const loadMore = () => getList(false)

	if (immediate) loadMore()

	return {
		page,
		list,
		total,
		...toRefs(state),
		getList,
		refresh,
		loadMore,
		isEmpty: computed(() => list.value.length === 0),
	}
}
